package com.niiwoo.civet.account.service.local.lend;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.niiwoo.asset.constant.MqConstants;
import com.niiwoo.asset.dto.mq.R360OrderStatusChangedDTO;
import com.niiwoo.asset.enums.r360.R360OrderProjectSubStatusEnum;
import com.niiwoo.asset.enums.r360.R360OrderStatusEnum;
import com.niiwoo.asset.org.business.constants.OrgRabbitConstant;
import com.niiwoo.asset.org.business.dto.mq.AutoWithdrawResultDTO;
import com.niiwoo.civet.account.dao.entity.AccountBase;
import com.niiwoo.civet.account.dao.entity.LendSuccessAccounting;
import com.niiwoo.civet.account.dao.entity.WithdrawOrder;
import com.niiwoo.civet.account.dao.mapper.LendSuccessAccountingMapper;
import com.niiwoo.civet.account.dto.SubmitLoanWithdrawRequestDTO;
import com.niiwoo.civet.account.dto.bill.AddBillAndChangeBalanceDTO;
import com.niiwoo.civet.account.dto.bill.AddBillDetailDTO;
import com.niiwoo.civet.account.dto.common.MoneyTotalDTO;
import com.niiwoo.civet.account.dto.request.LendSuccessAccountingRequestDTO;
import com.niiwoo.civet.account.dto.response.LendSuccessAccountingResponseDTO;
import com.niiwoo.civet.account.enums.*;
import com.niiwoo.civet.account.service.local.AccountBalanceLocalService;
import com.niiwoo.civet.account.service.local.AccountService;
import com.niiwoo.civet.account.service.local.MessageSendLocalService;
import com.niiwoo.civet.account.service.local.MoneyTotalLocalService;
import com.niiwoo.civet.account.service.local.bill.BillFacade;
import com.niiwoo.civet.account.service.local.bill.NiiwooBillFacade;
import com.niiwoo.civet.account.service.local.withdraw.WithdrawOrderService;
import com.niiwoo.civet.account.service.local.withdraw.WithdrawService;
import com.niiwoo.civet.base.enums.BorrowProjectTypeEnum;
import com.niiwoo.civet.base.enums.ChannelCodeEnum;
import com.niiwoo.civet.trade.dto.common.LendOrderDTO;
import com.niiwoo.civet.trade.dto.common.ProjectDTO;
import com.niiwoo.civet.trade.enums.ProjectFromSourceEnum;
import com.niiwoo.civet.trade.enums.TradeConfigEnum;
import com.niiwoo.civet.trade.service.configure.TradeConfigDubboService;
import com.niiwoo.civet.trade.service.lend.ProjectLendDubboService;
import com.niiwoo.civet.trade.service.project.ProjectDubboService;
import com.niiwoo.civet.user.dto.response.organization.OrganizationBaseConfigRespDTO;
import com.niiwoo.civet.user.service.OrganizationDubboService;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.provider.exception.BizException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * 标的放款记账服务
 *
 * @author liaojunjun
 */
@Service
public class ProjectLendAccountingLocalService {

    private static final Logger logger = LoggerFactory.getLogger(ProjectLendAccountingLocalService.class);

    @Autowired
    private MoneyTotalLocalService moneyTotalLocalService;

    @Autowired
    private PrivacyMasks privacyMasks;

    @Autowired
    private BillFacade billFacade;

    @Autowired
    private RabbitTemplate consistencyRabbitTemplate;

    @Autowired
    private MessageSendLocalService messageSendLocalService;

    @Autowired
    private WithdrawService withdrawService;
    
    @Autowired
    private AccountService accountService;

    @Reference(version = "1.0.0")
    private TradeConfigDubboService tradeConfigDubboService;

    @Autowired
    private AccountBalanceLocalService accountBalanceLocalService;

    @Reference(version = "1.0.0")
    private ProjectLendDubboService projectLendDubboService;

    @Reference(version = "1.0.0")
    private ProjectDubboService projectDubboService;
    
    @Reference(version = "1.0.0")
    private OrganizationDubboService organizationDubboService;

    @Autowired
    private LendSuccessAccountingMapper lendSuccessAccountingMapper;

    /**
     * 放款成功记账
     *
     * @param requestDTO
     * @return
     */
    public LendSuccessAccountingResponseDTO lendSuccessAccounting(LendSuccessAccountingRequestDTO requestDTO) {
        logger.info("lendSuccessAccounting requestDTO:{}", JSON.toJSON(requestDTO));
        LendSuccessAccountingResponseDTO result = new LendSuccessAccountingResponseDTO();
        Map<String, String> autoWithdrawConfigMap = null;
        if (ProjectFromSourceEnum.R360.getType().equals(requestDTO.getFromSource())
                || ProjectFromSourceEnum.CARD_NIU.getType().equals(requestDTO.getFromSource())

                || BorrowProjectTypeEnum.SMALL_LOAN.getValue().equals(requestDTO.getProjectType())
                || BorrowProjectTypeEnum.SOCIAL_SECURITY_LOAN.getValue().equals(requestDTO.getProjectType())
                || BorrowProjectTypeEnum.CREDIT_CARD_LOAN.getValue().equals(requestDTO.getProjectType())
                || BorrowProjectTypeEnum.CONSUME_LOAN.getValue().equals(requestDTO.getProjectType())

                || BorrowProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(requestDTO.getProjectType())

                || BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(requestDTO.getProjectType())) {
            autoWithdrawConfigMap = getAutoWithdrawConfigMap();
        }
        Long withdrawOrderId = ((ProjectLendAccountingLocalService) AopContext.currentProxy()).lendSuccessAccountingAndMoneyTotal(requestDTO,
                autoWithdrawConfigMap);
        result.setWithdrawOrderId(withdrawOrderId);
        logger.info("accounting succeed projectId:{}", requestDTO.getProjectId());
        return result;
    }

    /**
     * 账单处理，累计金额处理，自动提现
     *
     * @param requestDTO
     * @param autoWithdrawConfigMap
     * @return
     */
    @Transactional
    public Long lendSuccessAccountingAndMoneyTotal(LendSuccessAccountingRequestDTO requestDTO, Map<String, String> autoWithdrawConfigMap) {
        logger.info("lendSuccessAccountingAndMoneyTotal projectId:{}", requestDTO.getProjectId());
        LendSuccessAccounting lendSuccessAccounting = lendSuccessAccountingMapper.selectByPrimaryKey(requestDTO.getProjectId());
        if(lendSuccessAccounting != null){
            return lendSuccessAccounting.getWithdrawOrderId();
        }
        // 写入记账记录
        lendSuccessAccounting = new LendSuccessAccounting();
        lendSuccessAccounting.setProjectId(requestDTO.getProjectId());
        lendSuccessAccounting.setCreateTime(new Date());
        lendSuccessAccounting.setUpdateTime(new Date());
        lendSuccessAccountingMapper.insertSelective(lendSuccessAccounting);

        // 投资账单修改为成功
        for (LendSuccessAccountingRequestDTO.InvestSuccessBill investSuccessBill : requestDTO.getInvestSuccessBillList()) {
            if(requestDTO.getIsPackagedProject() != null && requestDTO.getIsPackagedProject()){
                billFacade.billIntelligenceInvestForRealProjectSuccess(investSuccessBill.getUserId(), investSuccessBill.getInvestOrderId().toString());
            }else {
                billFacade.successBillByOrderId(investSuccessBill.getUserId(), investSuccessBill.getInvestOrderId().toString(),
                        OrderTypeEnum.INVEST);
            }
        }

        //变更余额 + 记账
        List<AddBillDetailDTO> addBillDetailDTOList = new ArrayList<>();
        AddBillDetailDTO borrowIncomeBill = new AddBillDetailDTO();
        borrowIncomeBill.setAmount(requestDTO.getBorrowAmount());
        borrowIncomeBill.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_BORROW_INCOME_AMOUNT);
        addBillDetailDTOList.add(borrowIncomeBill);

        // 到手金额
        BigDecimal handAmount = requestDTO.getBorrowAmount();

        // 记录财富累计
        List<MoneyTotalDTO> moneyTotalDTOList = new ArrayList<>();

        ProjectDTO projectDTO = projectDubboService.selectProjectById(requestDTO.getProjectId());

        if(requestDTO.getManagementFee() != null && requestDTO.getManagementFee().compareTo(BigDecimal.ZERO) > 0) {
            // 提现金额
            handAmount = handAmount.subtract(requestDTO.getManagementFee());


            // 借款人平台管理费支出账单
            AddBillDetailDTO managementFeeBill = new AddBillDetailDTO();
            managementFeeBill.setAmount(requestDTO.getManagementFee());
            managementFeeBill.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_BORROW_MANAGE_FEE);
            managementFeeBill.setRemark("借款成标后，平台收取借款人平台管理费（前置）");
            addBillDetailDTOList.add(managementFeeBill);


            // 平台管理费收入账单
            AddBillDetailDTO managementFeeBillIn = new AddBillDetailDTO();
            managementFeeBillIn.setAmount(requestDTO.getManagementFee());
            managementFeeBillIn.setBillSecondSubjectEnum(BillSecondSubjectEnum.PLATFORM_BORROW_MANAGE_FEE);


            AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
            billDTO.setAccountId(requestDTO.getManagemenAccountId());
            billDTO.setAmount(requestDTO.getManagementFee());
            billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
            billDTO.setOrderId(requestDTO.getProjectId());
            billDTO.setOrderType(OrderTypeEnum.LEND);
            billDTO.setRequestNo(requestDTO.getRequestNo());
            billDTO.setStatus(BillStatusEnum.SUCCESS);
            billDTO.setChannelCode(ChannelCodeEnum.APP);
            billDTO.setProjectId(projectDTO.getProjectId());
            billDTO.setProjectType(BorrowProjectTypeEnum.enumOf(projectDTO.getType()));
            billDTO.setProjectTitle(projectDTO.getTitle());
            billDTO.setAddBillDetailDTOList(Arrays.asList(managementFeeBillIn));
            billFacade.addBillAndChangeBalance(billDTO);


            // 借款人平台管理费支出累计
            MoneyTotalDTO managementFee = new MoneyTotalDTO();
            managementFee.setAccountId(requestDTO.getBorrowerAccountId());
            managementFee.setAmountType(AccountAmountTypeEnum.BORROW_PLATFORM_MANAGER_FEE);
            managementFee.setAmount(requestDTO.getManagementFee());
            moneyTotalDTOList.add(managementFee);
        }

        if(requestDTO.getGuaranteeFee() != null && requestDTO.getGuaranteeFee().compareTo(BigDecimal.ZERO) > 0) {
            // 提现金额
            handAmount = handAmount.subtract(requestDTO.getGuaranteeFee());


            // 借款人担保服务费支出账单
            AddBillDetailDTO guaranteeFeeBill = new AddBillDetailDTO();
            guaranteeFeeBill.setAmount(requestDTO.getGuaranteeFee());
            guaranteeFeeBill.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_BORROW_GUARANTEE_SERVICE_FEE);
            addBillDetailDTOList.add(guaranteeFeeBill);


            // 担保服务费收入账单
            AddBillDetailDTO managementFeeBillIn = new AddBillDetailDTO();
            managementFeeBillIn.setAmount(requestDTO.getGuaranteeFee());
            managementFeeBillIn.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_GUARANTEE_FEE);

            AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
            billDTO.setAccountId(requestDTO.getGuaranteeAccountId());
            billDTO.setAmount(requestDTO.getGuaranteeFee());
            billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
            billDTO.setOrderId(requestDTO.getProjectId());
            billDTO.setOrderType(OrderTypeEnum.LEND);
            billDTO.setRequestNo(requestDTO.getRequestNo());
            billDTO.setStatus(BillStatusEnum.SUCCESS);
            billDTO.setChannelCode(ChannelCodeEnum.APP);
            billDTO.setProjectId(projectDTO.getProjectId());
            billDTO.setProjectType(BorrowProjectTypeEnum.enumOf(projectDTO.getType()));
            billDTO.setProjectTitle(projectDTO.getTitle());
            billDTO.setAddBillDetailDTOList(Arrays.asList(managementFeeBillIn));
            billFacade.addBillAndChangeBalance(billDTO);


            // 借款担保服务费支出累计
            MoneyTotalDTO guaranteeFee = new MoneyTotalDTO();
            guaranteeFee.setAccountId(requestDTO.getBorrowerAccountId());
            guaranteeFee.setAmountType(AccountAmountTypeEnum.BORROW_GUARANTEE_SERVICE_FEE);
            guaranteeFee.setAmount(requestDTO.getGuaranteeFee());
            moneyTotalDTOList.add(guaranteeFee);
        }

        if(requestDTO.getConsultingFee() != null && requestDTO.getConsultingFee().compareTo(BigDecimal.ZERO) > 0) {
            // 提现金额
            handAmount = handAmount.subtract(requestDTO.getConsultingFee());


            // 借款人咨询服务费支出账单
            AddBillDetailDTO consultingFeeBill = new AddBillDetailDTO();
            consultingFeeBill.setAmount(requestDTO.getConsultingFee());
            consultingFeeBill.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_BORROW_CONSULTING_FEE);
            addBillDetailDTOList.add(consultingFeeBill);


            // 咨询服务费收入账单
            AddBillDetailDTO consultingFeeBillIn = new AddBillDetailDTO();
            consultingFeeBillIn.setAmount(requestDTO.getConsultingFee());
            consultingFeeBillIn.setBillSecondSubjectEnum(BillSecondSubjectEnum.COOPERATE_BORROW_CONSULTING_FEE);

            AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
            billDTO.setAccountId(requestDTO.getConsultingAccountId());
            billDTO.setAmount(requestDTO.getConsultingFee());
            billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
            billDTO.setOrderId(requestDTO.getProjectId());
            billDTO.setOrderType(OrderTypeEnum.LEND);
            billDTO.setRequestNo(requestDTO.getRequestNo());
            billDTO.setStatus(BillStatusEnum.SUCCESS);
            billDTO.setChannelCode(ChannelCodeEnum.APP);
            billDTO.setProjectId(projectDTO.getProjectId());
            billDTO.setProjectType(BorrowProjectTypeEnum.enumOf(projectDTO.getType()));
            billDTO.setProjectTitle(projectDTO.getTitle());
            billDTO.setAddBillDetailDTOList(Arrays.asList(consultingFeeBillIn));
            billFacade.addBillAndChangeBalance(billDTO);


            // 借款咨询服务费支出累计
            MoneyTotalDTO consultingFee = new MoneyTotalDTO();
            consultingFee.setAccountId(requestDTO.getBorrowerAccountId());
            consultingFee.setAmountType(AccountAmountTypeEnum.BORROW_CONSULTING_FEE);
            consultingFee.setAmount(requestDTO.getConsultingFee());
            moneyTotalDTOList.add(consultingFee);
        }

        if(requestDTO.getBeforeSeekAdviceServiceFee() != null && requestDTO.getBeforeSeekAdviceServiceFee().compareTo(BigDecimal.ZERO) > 0) {
            // 提现金额
            handAmount = handAmount.subtract(requestDTO.getBeforeSeekAdviceServiceFee());


            // 借款人前置咨询服务费支出账单
            AddBillDetailDTO beforeSeekAdviceServiceFeeBill = new AddBillDetailDTO();
            beforeSeekAdviceServiceFeeBill.setAmount(requestDTO.getBeforeSeekAdviceServiceFee());
            beforeSeekAdviceServiceFeeBill.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_BORROW_PRE_FEE);
            addBillDetailDTOList.add(beforeSeekAdviceServiceFeeBill);

            // 借款前置咨询服务费收入账单
            AddBillDetailDTO beforeSeekAdviceServiceFeeBillIn = new AddBillDetailDTO();
            beforeSeekAdviceServiceFeeBillIn.setAmount(requestDTO.getBeforeSeekAdviceServiceFee());
            beforeSeekAdviceServiceFeeBillIn.setBillSecondSubjectEnum(BillSecondSubjectEnum.COOPERATE_BORROW_PRE_FEE);

            AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
            billDTO.setAccountId(requestDTO.getBeforeSeekAdviceServiceAccountId());
            billDTO.setAmount(requestDTO.getBeforeSeekAdviceServiceFee());
            billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
            billDTO.setOrderId(requestDTO.getProjectId());
            billDTO.setOrderType(OrderTypeEnum.LEND);
            billDTO.setRequestNo(requestDTO.getRequestNo());
            billDTO.setStatus(BillStatusEnum.SUCCESS);
            billDTO.setChannelCode(ChannelCodeEnum.APP);
            billDTO.setProjectId(projectDTO.getProjectId());
            billDTO.setProjectType(BorrowProjectTypeEnum.enumOf(projectDTO.getType()));
            billDTO.setProjectTitle(projectDTO.getTitle());
            billDTO.setAddBillDetailDTOList(Arrays.asList(beforeSeekAdviceServiceFeeBillIn));
            billFacade.addBillAndChangeBalance(billDTO);



            // 借款前置咨询服务费支出累计
            MoneyTotalDTO beforeSeekAdviceServiceFee = new MoneyTotalDTO();
            beforeSeekAdviceServiceFee.setAccountId(requestDTO.getBorrowerAccountId());
            beforeSeekAdviceServiceFee.setAmountType(AccountAmountTypeEnum.BORROW_BEFORE_SEEK_ADVICE_SERVICE_FEE);
            beforeSeekAdviceServiceFee.setAmount(requestDTO.getBeforeSeekAdviceServiceFee());
            moneyTotalDTOList.add(beforeSeekAdviceServiceFee);
        }

        AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
        billDTO.setAccountId(requestDTO.getBorrowerAccountId());
        billDTO.setAmount(handAmount);
        billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
        billDTO.setOrderId(requestDTO.getProjectId());
        billDTO.setOrderType(OrderTypeEnum.LEND);
        billDTO.setRequestNo(requestDTO.getRequestNo());
        billDTO.setStatus(BillStatusEnum.SUCCESS);
        billDTO.setChannelCode(ChannelCodeEnum.APP);


        billDTO.setProjectId(projectDTO.getProjectId());
        billDTO.setProjectType(BorrowProjectTypeEnum.enumOf(projectDTO.getType()));
        billDTO.setProjectTitle(projectDTO.getTitle());

        billDTO.setAddBillDetailDTOList(addBillDetailDTOList);
        billFacade.addBillAndChangeBalance(billDTO);
logger.info("moneyTotalDTOList1:{}", JSON.toJSONString(moneyTotalDTOList));
        moneyTotalDTOList.add(requestDTO.getBorrowTotal());
        moneyTotalDTOList.addAll(requestDTO.getInvestTotal());
        moneyTotalDTOList.addAll(requestDTO.getInvestFreeze());
        moneyTotalDTOList.addAll(requestDTO.getDueInCapitalInterest());

        // 使用accountId排序后处理金额累计防止并发下死锁
        Comparator<MoneyTotalDTO> accountIdSort = (MoneyTotalDTO t1, MoneyTotalDTO t2) -> (t1.getAccountId().compareTo(t2.getAccountId()));
logger.info("moneyTotalDTOList2:{}", JSON.toJSONString(moneyTotalDTOList));
        Collections.sort(moneyTotalDTOList, accountIdSort);
        moneyTotalLocalService.moneyTotal(moneyTotalDTOList);

        // 自动提现
        WithdrawOrder withdrawOrder = autoWithdraw(requestDTO, autoWithdrawConfigMap, handAmount);

        if(withdrawOrder != null){
            lendSuccessAccounting.setWithdrawOrderId(withdrawOrder.getId());
            lendSuccessAccounting.setCreateTime(null);
            lendSuccessAccountingMapper.updateByPrimaryKeySelective(lendSuccessAccounting);
            return withdrawOrder.getId();
        }
        return null;
    }

    @Autowired
    private WithdrawOrderService withdrawOrderService;

    /**
     * 自动提现结果通知
     *
     * @param withdrawOrderId
     * @param withdrawStatus
     */
    public void autoWithdrawResultNotify(Long withdrawOrderId, Byte withdrawStatus) {
            logger.info("autoWithdrawResultNotify, withdrawOrderId:{}, withdrawStatus:{}", withdrawOrderId, withdrawStatus);
        try {
            Assert.notNull(withdrawOrderId, "autoWithdrawResultNotify withdrawOrderId is null.");
            LendOrderDTO lendOrderDto = projectLendDubboService
                    .queryLendOrderByWithdrawOrderId(withdrawOrderId);
            if (lendOrderDto == null) {// 放款订单不存在
                logger.warn("自动提现对应放款订单不存在, withdrawOrderId:{}", withdrawOrderId);
                throw new BizException("ACC20012");
            }

            ProjectDTO project = projectDubboService.selectProjectById(lendOrderDto.getProjectId());
            boolean isCardLoan = project.getType().equals(com.niiwoo.civet.trade.enums.ProjectTypeEnum.CARD_NIU_LOAN.getValue());
            boolean isFormCardNiu = project.getFromSource().equals(ProjectFromSourceEnum.CARD_NIU.getType());
            if (isCardLoan && isFormCardNiu) {
                if (WithdrawOrderStatusEnum.FAIL.getCode().equals(withdrawStatus)) {
                    messageSendLocalService.sendMsgForWithdrawFailToCardNiu(project);
                }
            } else if(ProjectFromSourceEnum.R360.getType().equals(project.getFromSource())){
                R360OrderStatusChangedDTO r360OrderStatusChangedDTO = new R360OrderStatusChangedDTO();
                r360OrderStatusChangedDTO.setProjectId(lendOrderDto.getProjectId());
                r360OrderStatusChangedDTO.setUpdateDate(new Date());
                r360OrderStatusChangedDTO.setR360OrderProjectSubStatusEnum(R360OrderProjectSubStatusEnum.REPAYING_INIT);
                r360OrderStatusChangedDTO.setR360OrderStatusEnumCode(WithdrawOrderStatusEnum.SUCCESS.getCode().equals(
                        withdrawStatus) ? R360OrderStatusEnum.WITHDRAW_SUCCESS.getCode()
                        : R360OrderStatusEnum.WITHDRAW_FAILED.getCode());
                logger.info("autoWithdrawResultNotify, r360OrderStatusChangedDTO:{}", JSON.toJSON(r360OrderStatusChangedDTO));
                consistencyRabbitTemplate.convertAndSend(MqConstants.Exchange.ASSET_EXCHANGE, MqConstants.getRoutingKey(
                        MqConstants.Exchange.ASSET_EXCHANGE, MqConstants.Queue.ORDER_STATUS_NOFIFY_FOR_COMMON),
                        r360OrderStatusChangedDTO);
            } else if(BorrowProjectTypeEnum.SMALL_LOAN.getValue().equals(project.getType())
                    || BorrowProjectTypeEnum.SOCIAL_SECURITY_LOAN.getValue().equals(project.getType())
                    || BorrowProjectTypeEnum.CREDIT_CARD_LOAN.getValue().equals(project.getType())){
                if (WithdrawOrderStatusEnum.FAIL.getCode().equals(withdrawStatus)) {
                    messageSendLocalService.lendSuccessAutoWithdrawFailBorrowerNotify(project);
                }
            } else if(BorrowProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(project.getType())
                    || BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(project.getType())) {
                AutoWithdrawResultDTO autoWithdrawResultDTO = new AutoWithdrawResultDTO();
                autoWithdrawResultDTO.setProjectId(lendOrderDto.getProjectId());
                autoWithdrawResultDTO.setSuccess(WithdrawOrderStatusEnum.SUCCESS.getCode().equals(withdrawStatus));
                logger.info("autoWithdrawResultNotify, autoWithdrawResultDTO:{}", JSON.toJSON(autoWithdrawResultDTO));
                consistencyRabbitTemplate.convertAndSend(OrgRabbitConstant.Exchange.ORG_COMMON_DIRECT_EXCHANGE, OrgRabbitConstant.getRoutingKey(
                        OrgRabbitConstant.Exchange.ORG_COMMON_DIRECT_EXCHANGE, OrgRabbitConstant.Queue.AUTO_WITHDRAW_RESULT_NOTIFY_QUEUE),
                        autoWithdrawResultDTO);

                if (BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(project.getType())) {
                    if (WithdrawOrderStatusEnum.FAIL.getCode().equals(withdrawStatus)) {
                        WithdrawOrder withdrawOrder = withdrawOrderService.getWithdrawOrderByIdFromMaster(withdrawOrderId);
                        messageSendLocalService.sendMsgForWithdrawFailToTo8tu(project.getBorrowUserId(), withdrawOrder);
                    }
                }
            }
        } catch (Throwable e) {
            logger.error("自动提现结果通知失败", e);
        }

    }

    /**
     * 获取自动提现配置信息
     *
     * @return
     */
    private Map<String, String> getAutoWithdrawConfigMap() {
        List<TradeConfigEnum> tradeConfigEnumList = new ArrayList<>();
        tradeConfigEnumList.add(TradeConfigEnum.FASTWITHDRAWFEE);// 提现手续费率
        tradeConfigEnumList.add(TradeConfigEnum.SINGLEWITHDRAWMAXAMOUNT);// 单次提现最高收取多少
        return tradeConfigDubboService.selectTradeConfigByEmuns(tradeConfigEnumList);
    }

    /**
     * 自动提现
     *
     * @param requestDTO
     * @param autoWithdrawConfigMap
     * @param withdrawAmount
     * @return
     */
    private WithdrawOrder autoWithdraw(LendSuccessAccountingRequestDTO requestDTO,
                                       Map<String, String> autoWithdrawConfigMap, BigDecimal withdrawAmount) {
        // 自动提现;
        if (ProjectFromSourceEnum.R360.getType().equals(requestDTO.getFromSource())
                || ProjectFromSourceEnum.CARD_NIU.getType().equals(requestDTO.getFromSource())

                || BorrowProjectTypeEnum.SMALL_LOAN.getValue().equals(requestDTO.getProjectType())
                || BorrowProjectTypeEnum.SOCIAL_SECURITY_LOAN.getValue().equals(requestDTO.getProjectType())
                || BorrowProjectTypeEnum.CREDIT_CARD_LOAN.getValue().equals(requestDTO.getProjectType())
                || BorrowProjectTypeEnum.CONSUME_LOAN.getValue().equals(requestDTO.getProjectType())

                || BorrowProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(requestDTO.getProjectType())

                || BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(requestDTO.getProjectType())) {
            // 查询相关配置
            String withdrawFeeRateStr = autoWithdrawConfigMap.get(TradeConfigEnum.FASTWITHDRAWFEE.getConfigKey());
            String maxWithdrawFeeStr = autoWithdrawConfigMap
                    .get(TradeConfigEnum.SINGLEWITHDRAWMAXAMOUNT.getConfigKey());

            BigDecimal withdrawFeeRate = StringUtils.isEmpty(withdrawFeeRateStr) ? BigDecimal.ZERO : new BigDecimal(
                    withdrawFeeRateStr);
            BigDecimal maxWithdrawFee = StringUtils.isEmpty(maxWithdrawFeeStr) ? BigDecimal.ZERO : new BigDecimal(
                    maxWithdrawFeeStr);

//			AccountBase accountBase = accountService.getAccountBase(requestDTO.getBorrowerUserId(),
//            UserRoleEnum.BORROWERS);
            //因新网银行需要走加急T0，默认全额垫资，因此无需查询垫资金额，直接使用借款金额-手续费即可，暂时屏蔽此段代码
//			WithdrawT0CheckResponse withdrawT0CheckResponse = withdrawService.checkT0Enable(accountBase,
//					borrowMoneyTotal);

            SubmitLoanWithdrawRequestDTO request = new SubmitLoanWithdrawRequestDTO();
            //提现业务类型
            if (ProjectFromSourceEnum.R360.getType().equals(requestDTO.getFromSource())) {
                request.setBusinessType(WithdrawBusinessTypeEnum.R360_USER_LOAN);
            } else if (ProjectFromSourceEnum.CARD_NIU.getType().equals(requestDTO.getFromSource())) {
                request.setBusinessType(WithdrawBusinessTypeEnum.CARD_NIU_USER_LOAN);
            } else if(BorrowProjectTypeEnum.SMALL_LOAN.getValue().equals(requestDTO.getProjectType())
                    || BorrowProjectTypeEnum.SOCIAL_SECURITY_LOAN.getValue().equals(requestDTO.getProjectType())
                    || BorrowProjectTypeEnum.CREDIT_CARD_LOAN.getValue().equals(requestDTO.getProjectType())
                    || BorrowProjectTypeEnum.CONSUME_LOAN.getValue().equals(requestDTO.getProjectType())){
                request.setBusinessType(WithdrawBusinessTypeEnum.NORMAL_WITHDRAW);
            } else if(BorrowProjectTypeEnum.ORG_SPEEDLOAN_NEW.getValue().equals(requestDTO.getProjectType())
                    || BorrowProjectTypeEnum.DECORATION_LOAN.getValue().equals(requestDTO.getProjectType())){
                request.setBusinessType(WithdrawBusinessTypeEnum.ORG_USER_LOAN);
            }
            request.setUserId(requestDTO.getBorrowerUserId());// 用户ID
            request.setAccountId(requestDTO.getBorrowerAccountId());
            request.setAmount(withdrawAmount);// 提现金额
//			request.setAdvanceAmount(withdrawT0CheckResponse.getAdvanceAmount());// 垫资金额
            request.setMobileNo(privacyMasks.decryptPrivacy(requestDTO.getBorrowMobile()));// 用户注册手机号(解密后的)
            
            //自动提现手续费计算NEW 2018/05/10
        	AccountBase accountBase = accountService.loadAccountById(requestDTO.getBorrowerAccountId());
            if (accountBase == null) {
                throw new BizException("ACC10004"); //借款人账户不存在
            }
            if (accountBase.getOrgId() == null) {
                throw new BizException("ACC10028"); //未配置提现手续费率
            }
            
	        OrganizationBaseConfigRespDTO organizationBaseConfigRespDTO = organizationDubboService.selectOrganizationBaseConfigByOrgId(accountBase.getOrgId());
	        if (organizationBaseConfigRespDTO != null && organizationBaseConfigRespDTO.getWithdrawRateT0() != null) {
	        	request.setFeePaymentUserType(organizationBaseConfigRespDTO.getWithdrawType());
	        	
	        	withdrawFeeRate = organizationBaseConfigRespDTO.getWithdrawRateT0(); //默认快速提现
	        	maxWithdrawFee = organizationBaseConfigRespDTO.getWithdrawMaxFee();
	        }
	        
            request.setWithdrawFeeRate(withdrawFeeRate);// 提现手续费率
            request.setMaxWithdrawFee(maxWithdrawFee);// 最大提现手续费

            logger.info("自动提现 withdrawService.submitLoanWithdraw request:{}", JSON.toJSON(request));

            return withdrawService.submitLoanWithdraw(request);
        }

        return null;
    }

    public LendSuccessAccountingResponseDTO queryLendSuccessAccounting(Long projectId){
        LendSuccessAccounting lendSuccessAccounting = lendSuccessAccountingMapper.selectByPrimaryKey(projectId);
        LendSuccessAccountingResponseDTO lendSuccessAccountingResponseDTO = new LendSuccessAccountingResponseDTO();
        lendSuccessAccountingResponseDTO.setWithdrawOrderId(lendSuccessAccounting.getWithdrawOrderId());
        return lendSuccessAccountingResponseDTO;
    }
}
